package com.daiyang.lottery.dao.Handler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.daiyang.lottery.dao.dataobject.Encrypt;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.nio.charset.StandardCharsets;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 这是数据库加密的处理器 , 继承BaseTypeHandler<Encrypt> 还要加配置properties文件
// 配置文件内容如下：
// mybatis.configuration.type-handlers-package=com.daiyang.lottery.dao.Handler
@MappedTypes(Encrypt.class)  //被处理的类型
@MappedJdbcTypes(JdbcType.VARCHAR) //转化后的jdbc类型
public class EncryptTypeHandler extends BaseTypeHandler<Encrypt> {

    //密钥
    private  final byte[] KEY = "123456789abcdefg".getBytes(StandardCharsets.UTF_8);
    /**
     * 加密
     * @param ps  预编译sql语句
     * @param i    需要赋值的索引位置
     * @param parameter i位置被赋值的参数值
     * @param jdbcType  存入数据库的类型
     * @throws SQLException 异常
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Encrypt parameter, JdbcType jdbcType) throws SQLException {
        if(parameter == null||parameter.getValue()==null) {
            ps.setString(i, null);
            return;
        }
        System.out.println("EncryptTypeHandler setNonNullParameter 加密前的值："+ parameter.getValue());
        AES aes = SecureUtil.aes(KEY);
        String encryptValue = aes.encryptHex(parameter.getValue());
        System.out.println("EncryptTypeHandler setNonNullParameter 加密后的值："+ encryptValue);
        ps.setString(i, encryptValue);

    }

    /**
     * 解密
     * @param rs  结果集
     * @param columnName  索引名
     * @return
     * @throws SQLException
     */

    @Override
    public Encrypt getNullableResult(ResultSet rs, String columnName) throws SQLException {
        System.out.println("EncryptTypeHandler getNullableResult columName 解密前的值："+ rs.getString(columnName));
        return decrypt(rs.getString(columnName));
    }

    /**
     * 解密
     * @param rs  结果集
     * @param columnIndex  索引位置
     * @return
     * @throws SQLException
     */
    @Override
    public Encrypt getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        System.out.println("EncryptTypeHandler getNullableResult  columnIndex 解密前的值： "+ rs.getString(columnIndex));
        return decrypt(rs.getString(columnIndex));
    }

    /**
     * 解密
     * @param cs   存储过程
     * @param columnIndex  索引位置
     * @return
     * @throws SQLException
     */
    @Override
    public Encrypt getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        System.out.println("EncryptTypeHandler getNullableResult  columnIndex 解密前的值： "+ cs.getString(columnIndex));
        return decrypt(cs.getString(columnIndex));
    }

    private Encrypt decrypt(String value){
        if(value==null) {
            return null;
        }
        AES aes = SecureUtil.aes(KEY);
        String decryptValue = aes.decryptStr(value);
        return new Encrypt(decryptValue);
    }
}
